package export;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.text.ParseException;
import java.util.Locale;

import javax.swing.filechooser.FileFilter;

import neuron.Coord;
import neuron.Dendrite;
import neuron.Network;
import neuron.Neuron;
import neuron.Segment;
import neuron.file.NetmorphLoader;

public class NeuronToHOCExport {

	PrintWriter out;
	ByteArrayOutputStream buffer;
	
	
	public static FileFilter hocFilter = new FileFilter() {
		public String getDescription() { return "NEURON files (*.hoc)"; }
		public boolean accept(File f) { return f.isDirectory() || f.getName().toUpperCase().endsWith(".HOC"); } 
	};
	
	
	public NeuronToHOCExport() {
		buffer = new ByteArrayOutputStream();
		out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(buffer)));
	}
	
	private void outPoint(double x, double y, double z, double w)
	{
		out.format(Locale.US, "{pt3dadd(%f,%f,%f,%f)}\n", x, y, z, w);
	}
	
	public void createSoma(double x, double y, double z, double diam)
	{
		out.println("{create soma}");
		out.println("{access soma}");
		out.println("{nseg = 1}");
		out.println("{strdef color color = \"Blue\"}");
		out.println("{pt3dclear()}");
		outPoint(x-10, y+10, z, diam);
		outPoint(x+10, y+10, z, diam);
		outPoint(x+10, y-10, z, diam);
		outPoint(x-10, y-10, z, diam);
		out.println("{diam " + diam + "}");
		out.println("");
	}

	private void outputSegment(Segment s, String name, String parent, String color)
	{
		out.format("{create %s}\n", name);
		out.format("{connect %s(0), %s(1)}\n", name, parent);
		out.format("{access %s}\n", name);
		out.println("{nseg = 1}");
		out.format("{strdef color color = \"%s\"}\n", color);
		out.println("{pt3dclear()}");

		for (Coord c : s.getPoints()) {
			out.format(Locale.US, "{pt3dadd(%f,%f,%f,%f)}\n", c.x, c.y, c.z, c.d);
		}	
		out.println("");
		
		int bi = 0;
		for (Segment b : s.getBranches()) {
			outputSegment(b, name + "_" + bi, name, color);
			bi++;
		}
	}
	
	public void outputDendrite(Dendrite d, String name, String parent, String color)
	{
		outputSegment(d.root, name, parent, color);
	}
	
	public void outputNeuron(Neuron n)
	{
		outputNeuron(n, true, true, true);
	}

	public void outputNeuron(Neuron n, boolean soma, boolean basal, boolean apical)
	{
		// SOMA
		if (soma) {
			Coord somaCenter = n.getSoma().getPoints().get(0);
			createSoma(somaCenter.x, somaCenter.y, somaCenter.z, 10);
		}

		// BASALS
		if (basal) {
			int di = 0;

			for (Dendrite d : n.basalDendrites()) {
				outputDendrite(d, "dend_"+di, "soma", "Blue");
				di++;
			}
		}

		// APICAL
		if (apical) {
			outputDendrite(n.getApicalDendrite(), "apical_0", "soma", "Yellow");
		}
	}

	public void save(File f) throws IOException
	{
		out.flush();
		out.close();
		
		FileWriter fw = new FileWriter(f);
		fw.write(buffer.toString());
		fw.flush();
		fw.close();
	}
	

}
